using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using JGSY.CMS.LowCode.Platform.Application.Interfaces;
using JGSY.CMS.LowCode.Platform.Infrastructure.Configuration.Models;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services
{
    /// <summary>
    /// 多云存储管理器，统一管理各种存储提供商
    /// </summary>
    public class FileStorageManager : ICloudStorageService
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly ILogger<FileStorageManager> _logger;

        public FileStorageManager(
            IServiceProvider serviceProvider,
            ILogger<FileStorageManager> logger)
        {
            _serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 获取主要存储服务（按优先级顺序）
        /// </summary>
        private ICloudStorageService GetPrimaryStorageService()
        {
            // 按优先级顺序尝试获取存储服务
            var services = new[]
            {
                () => (_serviceProvider.GetService<AliyunOssStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("AliyunOssStorageService 未注册"),
                () => (_serviceProvider.GetService<TencentCosStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("TencentCosStorageService 未注册"),
                () => (_serviceProvider.GetService<HuaweiObsStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("HuaweiObsStorageService 未注册"),
                () => (_serviceProvider.GetService<LocalStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("LocalStorageService 未注册")
            };

            foreach (var serviceFactory in services)
            {
                try
                {
                    var service = serviceFactory();
                    if (service != null)
                    {
                        _logger.LogDebug("使用存储服务: {ServiceType}", service.GetType().Name);
                        return service;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "获取存储服务失败: {ServiceFactory}", serviceFactory.Method.Name);
                }
            }

            throw new InvalidOperationException("无法获取任何可用的存储服务");
        }

        /// <summary>
        /// 获取备用存储服务
        /// </summary>
        private ICloudStorageService GetFallbackStorageService(string? excludeProvider = null)
        {
            var services = new Dictionary<string, Func<ICloudStorageService>>
            {
                ["AliyunOss"] = () => (_serviceProvider.GetService<AliyunOssStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("AliyunOssStorageService 未注册"),
                ["TencentCos"] = () => (_serviceProvider.GetService<TencentCosStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("TencentCosStorageService 未注册"),
                ["HuaweiObs"] = () => (_serviceProvider.GetService<HuaweiObsStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("HuaweiObsStorageService 未注册"),
                ["Local"] = () => (_serviceProvider.GetService<LocalStorageService>() as ICloudStorageService) ?? throw new InvalidOperationException("LocalStorageService 未注册")
            };

            foreach (var kvp in services)
            {
                if (kvp.Key.Equals(excludeProvider, StringComparison.OrdinalIgnoreCase))
                    continue;

                try
                {
                    var service = kvp.Value();
                    if (service != null)
                    {
                        _logger.LogDebug("使用备用存储服务: {ServiceType}", service.GetType().Name);
                        return service;
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, "获取备用存储服务失败: {ServiceType}", kvp.Key);
                }
            }

            throw new InvalidOperationException("无法获取任何可用的备用存储服务");
        }

        /// <summary>
        /// 上传文件流到云存储
        /// 支持多云存储自动切换，优先使用主存储服务，失败时自动切换到备用服务
        /// </summary>
        /// <param name="file">要上传的文件流</param>
        /// <param name="fileName">文件名称</param>
        /// <param name="folder">存储文件夹路径，可选</param>
        /// <param name="contentType">文件MIME类型，可选</param>
        /// <returns>上传成功后的文件访问URL</returns>
        /// <exception cref="AggregateException">所有存储服务都失败时抛出</exception>
        public async Task<string> UploadAsync(Stream file, string fileName, string? folder = null, string? contentType = null)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.UploadAsync(file, fileName, folder, contentType);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务上传失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.UploadAsync(file, fileName, folder, contentType);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务上传也失败");
                    throw new AggregateException("所有存储服务都无法完成上传", ex, fallbackEx);
                }
            }
        }

        /// <summary>
        /// 上传表单文件到云存储
        /// 处理HTTP表单文件上传，支持多云存储自动故障转移
        /// </summary>
        /// <param name="file">HTTP表单文件对象</param>
        /// <param name="folder">存储文件夹路径，可选</param>
        /// <returns>上传成功后的文件访问URL</returns>
        /// <exception cref="AggregateException">所有存储服务都失败时抛出</exception>
        public async Task<string> UploadAsync(IFormFile file, string? folder = null)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.UploadAsync(file, folder);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务上传失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.UploadAsync(file, folder);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务上传也失败");
                    throw new AggregateException("所有存储服务都无法完成上传", ex, fallbackEx);
                }
            }
        }

        public async Task<List<string>> UploadBatchAsync(IEnumerable<IFormFile> files, string? folder = null)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.UploadBatchAsync(files, folder);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务批量上传失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.UploadBatchAsync(files, folder);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务批量上传也失败");
                    throw new AggregateException("所有存储服务都无法完成批量上传", ex, fallbackEx);
                }
            }
        }

        public async Task<Stream> DownloadAsync(string fileUrl)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.DownloadAsync(fileUrl);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务下载失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.DownloadAsync(fileUrl);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务下载也失败");
                    throw new AggregateException("所有存储服务都无法完成下载", ex, fallbackEx);
                }
            }
        }

        public async Task<bool> DeleteAsync(string fileUrl)
        {
            var results = new List<bool>();
            var exceptions = new List<Exception>();

            // 尝试从所有存储服务中删除
            var allServices = new[]
            {
                () => _serviceProvider.GetService<AliyunOssStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<TencentCosStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<HuaweiObsStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<LocalStorageService>() as ICloudStorageService
            };

            foreach (var serviceFactory in allServices)
            {
                try
                {
                    var service = serviceFactory();
                    if (service != null)
                    {
                        var result = await service.DeleteAsync(fileUrl);
                        results.Add(result);
                        _logger.LogDebug("从 {ServiceType} 删除文件结果: {Result}", service.GetType().Name, result);
                    }
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                    _logger.LogWarning(ex, "从存储服务删除文件失败");
                }
            }

            // 如果至少有一个服务成功删除，则认为删除成功
            var success = results.Any(r => r);
            if (!success && exceptions.Any())
            {
                throw new AggregateException("所有存储服务都无法删除文件", exceptions);
            }

            return success;
        }

        public async Task<int> DeleteBatchAsync(IEnumerable<string> fileUrls)
        {
            var totalDeleted = 0;
            var exceptions = new List<Exception>();

            var allServices = new[]
            {
                () => _serviceProvider.GetService<AliyunOssStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<TencentCosStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<HuaweiObsStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<LocalStorageService>() as ICloudStorageService
            };

            foreach (var serviceFactory in allServices)
            {
                try
                {
                    var service = serviceFactory();
                    if (service != null)
                    {
                        var deleted = await service.DeleteBatchAsync(fileUrls);
                        totalDeleted = Math.Max(totalDeleted, deleted); // 取最大值
                        _logger.LogDebug("从 {ServiceType} 批量删除文件数量: {Count}", service.GetType().Name, deleted);
                    }
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                    _logger.LogWarning(ex, "从存储服务批量删除文件失败");
                }
            }

            return totalDeleted;
        }

        public async Task<bool> ExistsAsync(string fileUrl)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.ExistsAsync(fileUrl);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务检查文件存在性失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.ExistsAsync(fileUrl);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务检查文件存在性也失败");
                    return false; // 默认返回false，而不是抛出异常
                }
            }
        }

        public async Task<CloudFileInfo?> GetFileInfoAsync(string fileUrl)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.GetFileInfoAsync(fileUrl);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务获取文件信息失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.GetFileInfoAsync(fileUrl);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务获取文件信息也失败");
                    return null; // 返回null而不是抛出异常
                }
            }
        }

        public async Task<List<CloudFileInfo>> ListFilesAsync(string? folder = null, int maxResults = 100)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.ListFilesAsync(folder, maxResults);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务列出文件失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.ListFilesAsync(folder, maxResults);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务列出文件也失败");
                    return new List<CloudFileInfo>(); // 返回空列表而不是抛出异常
                }
            }
        }

        public async Task<PreSignedUploadInfo> GeneratePreSignedUploadUrlAsync(string fileName, string? folder = null, TimeSpan? expiration = null)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.GeneratePreSignedUploadUrlAsync(fileName, folder, expiration);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务生成预签名上传URL失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.GeneratePreSignedUploadUrlAsync(fileName, folder, expiration);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务生成预签名上传URL也失败");
                    throw new AggregateException("所有存储服务都无法生成预签名上传URL", ex, fallbackEx);
                }
            }
        }

        public async Task<string> GeneratePreSignedDownloadUrlAsync(string fileUrl, TimeSpan? expiration = null)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.GeneratePreSignedDownloadUrlAsync(fileUrl, expiration);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务生成预签名下载URL失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.GeneratePreSignedDownloadUrlAsync(fileUrl, expiration);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务生成预签名下载URL也失败");
                    throw new AggregateException("所有存储服务都无法生成预签名下载URL", ex, fallbackEx);
                }
            }
        }

        public async Task<string> CopyAsync(string sourceUrl, string destinationPath)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.CopyAsync(sourceUrl, destinationPath);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务复制文件失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.CopyAsync(sourceUrl, destinationPath);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务复制文件也失败");
                    throw new AggregateException("所有存储服务都无法复制文件", ex, fallbackEx);
                }
            }
        }

        public async Task<string> MoveAsync(string sourceUrl, string destinationPath)
        {
            try
            {
                var primaryService = GetPrimaryStorageService();
                return await primaryService.MoveAsync(sourceUrl, destinationPath);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "主存储服务移动文件失败，尝试备用服务");
                
                try
                {
                    var fallbackService = GetFallbackStorageService();
                    return await fallbackService.MoveAsync(sourceUrl, destinationPath);
                }
                catch (Exception fallbackEx)
                {
                    _logger.LogError(fallbackEx, "备用存储服务移动文件也失败");
                    throw new AggregateException("所有存储服务都无法移动文件", ex, fallbackEx);
                }
            }
        }

        public async Task<StorageStatistics> GetStatisticsAsync(string? folder = null)
        {
            var allStats = new List<StorageStatistics>();
            var exceptions = new List<Exception>();

            var allServices = new[]
            {
                () => _serviceProvider.GetService<AliyunOssStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<TencentCosStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<HuaweiObsStorageService>() as ICloudStorageService,
                () => _serviceProvider.GetService<LocalStorageService>() as ICloudStorageService
            };

            foreach (var serviceFactory in allServices)
            {
                try
                {
                    var service = serviceFactory();
                    if (service != null)
                    {
                        var stats = await service.GetStatisticsAsync(folder);
                        allStats.Add(stats);
                    }
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                    _logger.LogWarning(ex, "获取存储统计信息失败");
                }
            }

            // 合并所有统计信息
            if (allStats.Any())
            {
                return new StorageStatistics
                {
                    TotalFiles = allStats.Sum(s => s.TotalFiles),
                    TotalSize = allStats.Sum(s => s.TotalSize),
                    FileTypeStats = MergeFileTypeStats(allStats.SelectMany(s => s.FileTypeStats)),
                    FolderStats = MergeFolderStats(allStats.SelectMany(s => s.FolderStats))
                };
            }

            // 如果没有任何统计信息，返回默认值
            return new StorageStatistics
            {
                TotalFiles = 0,
                TotalSize = 0
            };
        }

        private Dictionary<string, FileTypeStats> MergeFileTypeStats(IEnumerable<KeyValuePair<string, FileTypeStats>> stats)
        {
            var merged = new Dictionary<string, FileTypeStats>();
            
            foreach (var kvp in stats)
            {
                if (merged.ContainsKey(kvp.Key))
                {
                    merged[kvp.Key].Count += kvp.Value.Count;
                    merged[kvp.Key].TotalSize += kvp.Value.TotalSize;
                }
                else
                {
                    merged[kvp.Key] = new FileTypeStats
                    {
                        Count = kvp.Value.Count,
                        TotalSize = kvp.Value.TotalSize
                    };
                }
            }
            
            return merged;
        }

        private Dictionary<string, FolderStats> MergeFolderStats(IEnumerable<KeyValuePair<string, FolderStats>> stats)
        {
            var merged = new Dictionary<string, FolderStats>();
            
            foreach (var kvp in stats)
            {
                if (merged.ContainsKey(kvp.Key))
                {
                    merged[kvp.Key].FileCount += kvp.Value.FileCount;
                    merged[kvp.Key].SubFolderCount += kvp.Value.SubFolderCount;
                    merged[kvp.Key].TotalSize += kvp.Value.TotalSize;
                }
                else
                {
                    merged[kvp.Key] = new FolderStats
                    {
                        FileCount = kvp.Value.FileCount,
                        SubFolderCount = kvp.Value.SubFolderCount,
                        TotalSize = kvp.Value.TotalSize
                    };
                }
            }
            
            return merged;
        }
    }
}
